<script setup lang="ts">
import { computed } from 'vue'

const props = withDefaults(
  defineProps<{
    width: string
    height?: string
    depth?: string
    border: boolean
  }>(),
  {
    width: '100px',
    border: true,
  }
)

const measure = (full: string) => {
  let t,
    half = ''
  if ((t = full.match(/(\d+)(\D+)/))) {
    half = parseInt(t[1]) / 2 + t[2]
  } else {
    console.error('width参数格式错误， 需要传入CSS长度')
  }
  return {
    full: full,
    negFull: '-' + full,
    half: half,
    negHalf: '-' + half,
  }
}

const xWidth = computed(() => measure(props.width))
let yHeight, zDepth
if (props.height === undefined) {
  yHeight = xWidth
} else {
  yHeight = computed(() => measure(props.height as string))
}

if (props.depth === undefined) {
  zDepth = xWidth
} else {
  zDepth = computed(() => measure(props.depth as string))
}
</script>

<template>
  <div class="container">
    <div class="side" :class="border ? 'border' : ''">
      <slot></slot>
      <slot name="front">
        <div class="text">front</div>
      </slot>
    </div>

    <div class="side" :class="border ? 'border' : ''">
      <slot></slot>
      <slot name="back">
        <div class="text">back</div>
      </slot>
    </div>

    <div class="side" :class="border ? 'border' : ''">
      <slot></slot>
      <slot name="left">
        <div class="text">left</div>
      </slot>
    </div>

    <div class="side" :class="border ? 'border' : ''">
      <slot></slot>
      <slot name="right">
        <div class="text">right</div>
      </slot>
    </div>

    <div class="side" :class="border ? 'border' : ''">
      <slot></slot>
      <slot name="top">
        <div class="text">top</div>
      </slot>
    </div>

    <div class="side" :class="border ? 'border' : ''">
      <slot></slot>
      <slot name="bottom">
        <div class="text">bottom</div>
      </slot>
    </div>
  </div>
</template>

<style scoped>
.container {
  transform-style: preserve-3d;
}

.side {
  position: absolute;
}

.side.border {
  border: 2px solid #1c1c1c;
}

.side:nth-child(1) {
  width: v-bind('xWidth.full');
  height: v-bind('yHeight.full');
  transform: translateZ(v-bind('zDepth.half'));
}

.side:nth-child(2) {
  width: v-bind('xWidth.full');
  height: v-bind('yHeight.full');
  transform: translateZ(v-bind('zDepth.negHalf')) rotateY(180deg);
}

.side:nth-child(3) {
  width: v-bind('zDepth.full');
  height: v-bind('yHeight.full');
  transform: translateZ(v-bind('zDepth.negHalf')) rotateY(-90deg);
  transform-origin: left;
}

.side:nth-child(4) {
  width: v-bind('zDepth.full');
  height: v-bind('yHeight.full');
  transform: rotateY(90deg) translateX(v-bind('zDepth.negHalf'))
    translateZ(v-bind('xWidth.full'));
  transform-origin: left;
}

.side:nth-child(5) {
  width: v-bind('xWidth.full');
  height: v-bind('zDepth.full');
  transform: rotateX(90deg) translateY(v-bind('zDepth.negHalf'));
  transform-origin: top;
}

.side:nth-child(6) {
  width: v-bind('xWidth.full');
  height: v-bind('zDepth.full');
  transform: rotateX(-90deg) translateY(v-bind('zDepth.negHalf'))
    translateZ(v-bind('yHeight.full'));
  transform-origin: top;
}

.side > div {
  width: 100%;
  height: 100%;
}

.text {
  text-align: center;
  align-content: center;
}
</style>
